# -*- coding: utf-8 -*-

from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.core.urlresolvers import reverse
from django.core import serializers

from achievements.models import Achievement, SubAchievement, Fulfilment, Category, Evidence
from achievements.forms import *
from accounts.models import Messages

from django.contrib.auth.models import User

from captcha.fields import ReCaptchaField

import datetime, json


SELECT_GLOB_ALL_QUERY = 'SELECT * FROM achievements_achievement WHERE achievements_achievement.hidden != 1'

SELECT_ONE_QUERY = 'SELECT * FROM achievements_achievement WHERE achievements_achievement.uuid = %s'


class ReCaptchaForm(forms.Form):
    captcha = ReCaptchaField(attrs={'theme' : 'blackglass'}, error_messages=dict(required='Táto položka je povinná.'))

def show_tables(request):
    
    result_list = None
    search_request = None
    
    achievement_list = dict.fromkeys(Achievement.objects.raw(SELECT_GLOB_ALL_QUERY), False)    
    
    if len(achievement_list) == 0:
        achievement_list = None
    
    if request.method == 'GET':
        search_request = request.GET.get('q', None)
        if search_request != None:
            result_list = Achievement.objects.filter(name__contains = search_request)
    
    if request.user.is_authenticated and achievement_list:
        for achi in achievement_list.keys():
            achievement_list[achi] = is_achievement_complete(request.user, achi)
            
    
    category_list = dict.fromkeys(Category.objects.all())
    if len(category_list) == 0:
        category_list = None
        
    if category_list and achievement_list:
        for cat in category_list.keys():
            category_list[cat] = []
            for achi, complete in achievement_list.iteritems():
                if achi.category and achi.category.id == cat.id:
                    category_list[cat].append(tuple([achi, complete]))
            
    
    return render_to_response('achievements/index.html', 
        {'achievement_list': achievement_list, 'category_list':category_list, 'result_list':result_list, 'search_request':search_request}, context_instance=RequestContext(request))


'''
def show_tables_users(request):
    achievement_list = dict.fromkeys(Achievement.objects.raw(SELECT_USER_ALL_QUERY))
    if len(achievement_list) == 0:
        achievement_list = None
    
    if request.user.is_authenticated and achievement_list:
        for achi in achievement_list.keys():
            achievement_list[achi] = is_achievement_complete(request.user, achi)
    
    return render_to_response('achievements/users.html', 
        {'achievement_list': achievement_list}, context_instance=RequestContext(request))
'''

def achievement_json(request, achievement_id):
    achievement_list = Achievement.objects.raw(SELECT_ONE_QUERY, [achievement_id])
    
    data = None
    
    if len(list(achievement_list)) > 0:
        data = serializers.serialize("json", achievement_list)
        
        data = json.loads(data)

        for d in data:
            del d['pk']
            del d['model']

        data = json.dumps(data)
        
    return render_to_response('api.html', {'data': data }, context_instance=RequestContext(request))

def show_achievement(request, achievement_id):
    achievement_list = Achievement.objects.raw(SELECT_ONE_QUERY, [achievement_id])
    
    achievement = None
    sub_achievement_list = None
    fulfilment = None
    dependency_list = None
    missing_dep = False
    past_deadline = False
    evidence = None
    
    if len(list(achievement_list)) > 0:
        achievement = achievement_list[0]
        
        #dependency_list.fromkeys(achievement.dependencies.all())
        
        sub_achievement_list = dict.fromkeys(SubAchievement.objects.filter(parent = achievement.id))
        
        if request.user.is_authenticated:
            fulfilment_list = Fulfilment.objects.filter(user = request.user.id, achievement = achievement.id)

            if len(list(fulfilment_list)) > 0:
                fulfilment = fulfilment_list[0]
                
                if request.method == 'POST' and not fulfilment.evidence:
                    evidence_file = None
                    
                    evidence_list = Evidence.objects.filter(user = request.user, achievement = achievement)
                    
                    if 'evidence_file' in request.FILES and len(list(evidence_list)) == 0:
                        evidence_file = request.FILES['evidence_file']
                    
                        e = Evidence(user = request.user,
                                     achievement = achievement,
                                     description = request.POST['evidence_desc'])
                        e.save()
                        
                        if evidence_file:
                            e.evidenceFile.save(evidence_file.name, evidence_file)
                        
                        fulfilment.evidence = e
                        fulfilment.save()
                        
                        message = Messages(author = request.user, recipient = fulfilment.achievement.author, header = "Požiadavka na schválenie", message_type = 'EM', evidence = e)
                        
                        message.save()
                        
                
                for v in sub_achievement_list.keys():
                    if fulfilment.subachievement.all().filter(id = v.id):
                        sub_achievement_list[v] = True
                        
            dependency_list = dict.fromkeys(achievement.dependencies.all())
            for dep in dependency_list.keys():
                tmp_flist = Fulfilment.objects.filter(user = request.user.id, achievement = dep.id)
                
                if (len(tmp_flist) > 0) and (tmp_flist[0].progress >= dep.progressMax):
                    dependency_list[dep] = True
                else:
                    dependency_list[dep] = False
                    missing_dep = True
            
    
#    form = ReCaptchaForm()
    
    return render_to_response('achievements/achievement.html',
        {'achievement': achievement, 'subachievements' : sub_achievement_list, 'fulfilment':fulfilment, 'dependencies':dependency_list, 'missing_dep':missing_dep, 'past_deadline':past_deadline }, context_instance=RequestContext(request))


def join_achievement(request, achievement_id):
    achievement_list = Achievement.objects.raw(SELECT_ONE_QUERY, [achievement_id])
    
    achievement = None
    password_form = None
    password_correct = 0
    fulfilment = None
    
    if len(list(achievement_list)) > 0:
        achievement = achievement_list[0]
        
        if not request.user.is_authenticated():
            return HttpResponseRedirect(reverse('show_one_achievement', args=[achievement.uuid]))
    
        fulfilment_list = Fulfilment.objects.filter(user = request.user.id, achievement = achievement.id)
        if len(list(fulfilment_list)) > 0:
            fulfilment = fulfilment_list[0]
            return render_to_response('achievements/join.html',
                {'achievement':achievement, 'fulfilment':fulfilment}, context_instance=RequestContext(request))
    
        if achievement.past_deadline:
            return HttpResponseRedirect(reverse('show_one_achievement', args=[achievement.uuid]))
    
        if achievement.password:
            
            if request.method == 'POST':
                form = PasswordForm(request.POST)
                if form.is_valid():
                    if form.cleaned_data['password'] == achievement.password:
                        password_correct = 1
                        create_fulfilment(achievement, request.user)
                    else:
                        password_correct = 2
            
            password_form = PasswordForm()
    
            return render_to_response('achievements/join.html',
                {'achievement':achievement, 'password_form':password_form, 'password_correct':password_correct, 'fulfilment':fulfilment}, context_instance=RequestContext(request))
        
        create_fulfilment(achievement, request.user)
    
    return HttpResponseRedirect(reverse('show_one_achievement', args=[achievement.uuid]))


def join_subachievement(request, achievement_id, sub_id):
    achievement_list = Achievement.objects.raw(SELECT_ONE_QUERY, [achievement_id])
    achievement = None
    
    if len(list(achievement_list)) == 0:
        return HttpResponseRedirect(reverse('show_one_achievement', args=[achievement.uuid]))
    else:
        achievement = achievement_list[0]   
    
    tmp_flist = Fulfilment.objects.filter(user = request.user.id, achievement = achievement.id)
    if len(list(tmp_flist)) > 0:
        f = tmp_flist[0]
        
        if len(list(f.subachievement.filter(id = sub_id))) > 0:
            return HttpResponseRedirect(reverse('show_one_achievement', args=[achievement.uuid]))
        
        tmp_sublist = SubAchievement.objects.filter(parent = achievement.id, id = sub_id)
        if len(list(tmp_sublist)) > 0:
            sub = tmp_sublist[0]
            f.subachievement.add(sub)
            
            add_points(request.user, sub.points)
            
            f.save()
            
    return HttpResponseRedirect(reverse('show_one_achievement', args=[achievement.uuid]))

    
def create_fulfilment(achi, user):
    tmp_flist = Fulfilment.objects.filter(user = user.id, achievement = achi.id)
    if len(list(tmp_flist)) > 0:
        return

    f = Fulfilment(user = user, achievement = achi)
    
    if achi.progressMax == 0 and not achi.evidenceRequired:
        f.awarded = True
        add_points(user, achi.points)
    
    f.save()
    
    
def is_achievement_complete(user, achievement):
    tmp_flist = Fulfilment.objects.filter(user = user.id, achievement = achievement.id)
    if len(list(tmp_flist)) > 0:
        f = tmp_flist[0]
        return f.progress >= achievement.progressMax
        
    return False
    
def add_points(user, toadd):
    user.userprofile.user_points += toadd
    user.userprofile.save()
    

def edit_achievement(request, achievement_id):
    return render_to_response('achievements/edit.html', {}, context_instance=RequestContext(request))
    
def create_achievement(request):
    if not request.user.is_authenticated():
        return render_to_response('achievements/create.html', {}, context_instance=RequestContext(request))
    
    achievement_list = list(Achievement.objects.raw(SELECT_GLOB_ALL_QUERY))
    max_points = 0
    if request.user.userprofile.user_points > 0:
        max_points = request.user.userprofile.user_points / 10
        
    max_sub_points = 0
    if max_points > 0:
        max_sub_points = max_points / 10
    
    errors = {}
    parsed_data = None
    error = 0
    form = ReCaptchaForm()
    time = None
    a = None
    
    uri = ""
    if 'SERVER_NAME' in request.META and 'SERVER_PORT' in request.META:
        uri = "http://" + request.META['SERVER_NAME'] + ":" + request.META['SERVER_PORT']
    
    file_pic = None
    
    if request.method == 'POST':
        error = 1
        
        parsed_data = dict(request.POST)
        
        if 'a_picture' in request.FILES:
            file_pic = request.FILES['a_picture']
        
        rcf = ReCaptchaForm(request.POST)
        if rcf.is_valid():
            errors['recaptcha_valid'] = True
        else:
            errors['recaptcha_valid'] = False
            error = 2
        
        
        if len(request.POST['a_password']) > 0:
            parsed_data['a_password'] = None
            errors['password_again'] = True
            
        if 'sub_name' in parsed_data:
            parsed_data['subs'] = []
            
            for i in range(len(parsed_data['sub_name'])):
                parsed_data['subs'].append([parsed_data['sub_name'][i], parsed_data['sub_desc'][i], parsed_data['sub_reward'][i], [] ])
                
                if not parsed_data['sub_name'][i]:
                    parsed_data['subs'][-1][-1].append("Chýba meno podúlohy")
                    error = 2
                else:
                    parsed_data['subs'][-1][-1].append("")
                    
                if not parsed_data['sub_desc'][i]:
                    parsed_data['subs'][-1][-1].append("Chýba popis podúlohy")
                    error = 2
                else:
                    parsed_data['subs'][-1][-1].append("")
                    
                if not parsed_data['sub_reward'][i]:
                    parsed_data['subs'][-1][-1].append("Chýba odmena podúlohy")
                    error = 2
                else:
                    if int(parsed_data['sub_reward'][i]) > max_sub_points or int(parsed_data['sub_reward'][i]) < 0:
                        parsed_data['subs'][-1][-1].append("Nesprávna hodnota")
                        error = 2
                    else:
                        parsed_data['subs'][-1][-1].append("")
                
            
            parsed_data.pop('sub_name')
            parsed_data.pop('sub_desc')
            parsed_data.pop('sub_reward')
            
        if 'dep_name' in parsed_data:
            parsed_data['dep_name'] = list(set(parsed_data['dep_name']))
            
        
        if not request.POST['a_name']:
            errors['name'] = 'Prosím zadajte meno achievementu'
            error = 2
            
        if not request.POST['a_desc']:
            errors['description'] = 'Prosím zadajte popis achievementu'
            error = 2
            
        if not request.POST['a_reward']:
            errors['reward'] = 'Chýba hodnota'
            error = 2
        else:
            if int(request.POST['a_reward']) > max_points or int(request.POST['a_reward']) < 0:
                errors['reward'] = 'Nesprávna hodnota'
                error = 2
            
        if request.POST['a_deadline']:
            try:
                time = datetime.datetime.strptime(str(request.POST['a_deadline']), '%d.%m.%Y')
                if time < datetime.datetime.now():
                    errors['deadline'] = 'Nesprávny dátum, dátum musí byť v budúcnosti'
                    error = 2
            except ValueError:
                errors['deadline'] = 'Nesprávny formát, prosím zadajte dátum vo formáte deň.mesiac.rok'
                error = 2
            
        if request.POST['a_progress']:
            if int(request.POST['a_progress']) <= 0:
                errors['progress'] = 'Priebeh musí byť najmenej 1, ak chcete achievement bez priebehu, nechajte toto políčko prázdne'
                error = 2
                
            
        if error == 1:
            a = Achievement(name = request.POST['a_name'],
                            description = request.POST['a_desc'],
                            points = int(request.POST['a_reward']),
                            author = request.user,
                            progressMax = int(request.POST['a_progress']) if 'a_progress' in request.POST and request.POST['a_progress'] else 0,
                            hidden = request.POST['a_hidden'] if 'a_hidden' in request.POST else False,
                            evidenceRequired = request.POST['a_evidence'] if 'a_evidence' in request.POST else False,
                            password = request.POST['a_password'],
                            deadline = time,
                            category = list(Category.objects.filter(name = request.POST['a_category']))[0] if request.POST['a_category'] != "---" else None)
            a.save()
            
            if file_pic:
                a.image.save(file_pic.name, file_pic)
            
            if 'dep_name' in request.POST:
                if isinstance(request.POST['dep_name'], basestring):
                    a.dependencies.add(list(Achievement.objects.filter(name = request.POST['dep_name']))[0])
                else:
                    for dep in request.POST['dep_name']:
                        a.dependencies.add(list(Achievement.objects.filter(name = dep))[0])
                        
            if 'subs' in parsed_data:
                for sub in parsed_data['subs']:
                    s = SubAchievement(parent = a,
                                       name = sub[0],
                                       description = sub[1],
                                       points = int(sub[2]))
                    s.save()
                
                    
            parsed_data = None
            errors = None
        
    category_list = list(Category.objects.all())
    
    return render_to_response('achievements/create.html', {'raw_autofill_data':achievement_list, 'data':parsed_data, 'max_points':max_points, 'max_sub_points':max_sub_points, 'errors':errors, 'state': error, 'form':form, 'achievement':a, 'categories':category_list, 'file_pic':file_pic, 'uri':uri },
        context_instance=RequestContext(request))